package 设计模式.创建型模式;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*
泛型实例化不论是什么类型，都将实例化的过程都用了同一种的实例化方法
mType = clz.newInstance();
这样做，即便不使用Integer，当我们需要把某个自定义的类默认构造方法声明为private时，上面的方法也不适用了。那怎样解决这
个问题呢？答案就是java编程的六大基本原则之一的面向接口编程。接口的好处就是把具体实现分割开，针对不同的需求，各自实现
自己想要的结果，互相之间不干扰。

首先声明一个接口，接口里声明一个方法，此方法用来创建泛型所代表类的实例
*/
//interface Creator<T> {
//    T create();
//}
///*
//这里还是以自定义的Trainer类实例化为例。创建一个用来把泛型类和实例化结果关联起来的工厂类，工厂类不关心具体的实例化过
//程，它只负责将实例化结果赋值给泛型类。工厂类的构造方法是一个泛型方法，泛型的边界是接口Creator，同时构造方法的参数是
//实现了Creator接口的子类。在子类的create()方法里是具体的类实例化过程。
//*/
//class Factory<T> {
//    private T t;//
//    public <C extends Creator<T>> Factory(C creator) {//构造函数：入参为希望实例化的实例。
//        t = creator.create();//将实例化结果与泛型类关联
//    }
//    public T getT() {
//   	 return t;//通过Factory的实例的getT方法获得泛型类实例
//    }
//}
//
//class Trainer {//需要实例化的类 -->通过接口方法创建
//   @Override
//   public String toString() {//实例方法具体工作内容
//       return "Trainer";
//   }
//   public void prin() {
//   	System.out.println("prin======");
//   }
//}
////在Factory类里，通过调用实现了Creator接口子类的create()方法创建实例。接下来，创建一个Trainer Creator类来实现Creator接口
//
////public class Factory泛型方法创建类实例 implements Creator<Integer> {
////public class Factory泛型方法创建类实例 implements Creator<String> {
//public class Factory泛型方法创建类实例 implements Creator<Trainer> {
//    @Override //覆写接口方法
//    public Trainer create() {//获取Trainer实例
//        return new Trainer();
//    }
//
//    //@Override //覆写接口方法
//    //public String create() {//获取String的实例 -->字符串
//    //    return "String";
//    //}
//    
//    //@Override //覆写接口方法
//    //public Integer create() {////获取Integer的实例 -->整数
//    //    return 100;
//    //}
//    
//    public static void main(String[] args) {
//   	 //Factory<Integer> factory = new Factory<>(new Factory泛型方法创建类实例());//
//       //Integer trainer = factory.getT();
//       //System.out.println(trainer.toString());
//   	 
//   	//Factory<String> factory = new Factory<String>(new Factory泛型方法创建类实例());//
//      //String trainer = factory.getT();
//      //System.out.println(trainer.toString());
//
//      Factory<Trainer> factory = new Factory<Trainer>(new Factory泛型方法创建类实例());//
//      Trainer trainer = factory.getT();
//      System.out.println(trainer.toString());
//      trainer.prin();
//    }
//}

//可以看到，类的实例化也就是new动作放在了具体的实现类里，而Factory的作用类似于适配器一样，它负责将Creator接口实现类
//的create()方法返回的类实例赋值给泛型类。这样做，大大降低了代码的耦合度。假如，此时需要一个Integer类型的值。那么只
//需要实现Creator接口创建一个新的用于创建Integer实例的实现类就可以了
/*
public class Factory方法创建类实例 implements Creator<Integer> {
    //@Override
    public Integer create() {
        return 1;
    }

    public static void main(String[] args) {
        Factory<Integer> factory = new Factory<Integer>(new Factory方法创建类实例());
        Integer integer = factory.getT();
        System.out.println(integer.toString());
    }
}
*/
/*
interface Creator<T>{
	T create();
}

class Factory<T>{
	private T t;                 //传入一个实现接口方法的过渡类实例
	//                                        ↓ 
	public <C extends Creator<T>> Factory(C creator) {
		t=creator.create();
	}
	public T getT() {
		return t;
	}
}

class Trainer{
	public String meth1(){
		return "meth1";
	}
	public void meth2(String str) {
		System.out.println(str);
	}
}

class Other implements Creator<Trainer>{//实现接口方法的过渡类
	@Override
	public Trainer create() {
		return new Trainer();
	}
}

public class Factory泛型方法创建类实例 implements Creator<Trainer>{
	@Override
	public Trainer create() {//必须覆写Creator接口
		return new Trainer();
	}
	public static void main(String[] args) {        //      C creator
		                                             //          ↓     
		Factory<Trainer> factory=new Factory<Trainer>(new Factory泛型方法创建类实例());//调用new Factory时已经生成代表Trainer的实例t
		//Factory<Trainer> factory=new Factory<Trainer>(new Other());//亦可
		Trainer trainer=factory.getT();
		System.out.println(trainer.meth1());
		trainer.meth2("meth2");
	}
}*/

//上面的例子需要中间过渡类，下面是不需要中间过渡类，而直接获得类实例的方法：
interface Factory<T> {
   T getProduct(Class<? extends T> clazz);
}

class GenericFactory<T> implements Factory<T> {
   @Override
   public T getProduct(Class<? extends T> clazz) {
       if (clazz == null)
           return null;

       try {
      	 T obj=clazz.getDeclaredConstructor().newInstance();
           //T obj = clazz.newInstance();//弃用，原因是无参构造异常无法被捕获
           return obj;
       
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
      	 e.printStackTrace();
       } catch (NoSuchMethodException e) {
      	 e.printStackTrace();
       }  catch (InstantiationException e) {
      	 e.printStackTrace();
       }
       return null;
   }
}

public class Factory泛型方法创建类实例 {

   public static void main(String[] args) {
       Factory<Car> carFactory = new GenericFactory<>();
       Factory<Television> tvFactory = new GenericFactory<>();
       
       Car benz = carFactory.getProduct(Benz.class);//由于接口方法入参使用<? extends T>,且设立Car接口，所以可以直接用具体Class
       Car audi = carFactory.getProduct(Audi.class);
       benz.run();
       audi.run();
       
       Television sonyTV = tvFactory.getProduct(SonyTV.class);
       Television sharpTV = tvFactory.getProduct(SharpTV.class);
       sonyTV.play();
       sharpTV.play();
   }
}
interface Car {//利于代入时直接用具体类名
   void run();
}
class Audi implements Car{
   @Override
   public void run() {
       System.out.println("Audi running...");
   }
}
class Benz implements Car{
   @Override
   public void run() {
       System.out.println("Benz running...");
   }
}

interface Television {
   void play();
}
class SonyTV implements Television{
   @Override
   public void play() {
       System.out.println("SonyTV playing...");
   }
}
class SharpTV implements Television{
   @Override
   public void play() {
       System.out.println("SharpTV playing...");
   }
}
